<template>
    <!--vue3的可以类似vue2,兼容，但是建议都是用组合式的方式进行声明-->
    <h1>人员列表</h1>
    <ul v-for="(p, index) in PersonList" :key="index">
        <li>姓名 {{ p.name }} --- 年龄 {{ p.age }}</li>
    </ul>
    <!--模板使用的时候不需要使用.value-->
    <span>当前的cnt值是:{{ cnt }}</span>
    <button @click="increase">点我cnt+1</button>
    <hr>
    <div>
        <span>姓{{ per.firstName }}</span>
        <hr>
        <span>名{{ per.lastName }}</span>
        <hr>
        <span>全名是{{ fullName }}</span>
        <button @click="changeName">点我修改名字</button>
    </div>
    <hr>
    <ul>
        <li v-for="t in list" :key="t.id">
            内容为:{{ t.content }}
        </li>
    </ul>
</template>

<script setup lang="ts">

import { ref, reactive, computed, watch, onMounted, watchEffect, toRef, toRefs } from 'vue';
import { SexType, type Persons } from '../types/types';
import { useTalkStore } from '../store/talk';
//定义person列表
const PersonList = reactive<Persons>([
    { name: 'chy', age: 18 },
    { name: 'xxx', age: 19 },
    { name: 'yyy', age: 20 },
    { name: 'zzz', age: 18, sex: SexType.Female },
])
//ref的使用，ref可以定义响应式基本数据，也可以获取响应式对象数据--->既然是对象，建议用reactive
let cnt = ref(0)
function increase() {
    cnt.value++ //对于ref的响应式数据，需要使用.value进行访问真正的数据
}
//computed函数，依旧是函数方式
let obj = reactive({
    name: 'chy',
    age: 18,
})
//计算属性，computed，生成一个计算属性，这个属性本质是一个ref对象,默认是只读的
let a = computed(() => {
    return "a"
})
//完整写法需要使书写get和set函数
let per = reactive({
    firstName: '1',
    lastName: '2'
})
let fullName = computed({
    get() {
        return per.firstName + '-' + per.lastName
    },
    set(value: string) {
        console.log('修改姓名')
        const arr: string[] = value.split('-')
        per.firstName = arr[0]
        per.lastName = arr[1]
    }
}
)
function changeName() {
    fullName.value = "zhan-san"
}
/*
1.使用watch监视对响应对象
监视ref定义的响应式对象，需要手动开启深度监视
*/
let c = ref({
    name: 'c',
    age: 18
})
watch(c, (newVal: any, oldVal: any) => {
    console.log('@@@', newVal, oldVal)
}, { deep: true })
function changecName() {
    c.value.name = '11111' //这种情况尚未输出内容
    c.value = { name: '2222', age: 18 }
}
/*
情况2：watch监视reactive定义对象
reative对象默认监视就是深度的
*/
let d = reactive({
    name: 'chy',
    age: 18
})
watch(d, (newVal: any, oldVal: any) => {
    console.log('*****', newVal, oldVal)
})
function changDName() {
    d.name = '11111'
    /*
    修改默认的reactive对象的语法
     Object.assign({name:"123",age:20},d) --->本质就是重新对属性赋值，没有改变对象地址
    */
}
/*
情况3：监视多个ref定义的数据，其实就是newValue和oldVal变成了一一对应的数组
*/
watch([cnt, c], (newVal: any, oldVal: any) => {
    console.log('########', newVal, oldVal);
})
/*
情况4：监视reactive定义对象的属性，第一个参数需要写成一个函数,单独读取对象的属性的时候
对应的深度监听都是有效的，如果需要进行深度监听就需要配置deep参数
*/
watch(() => d.name, (newVal: any, oldVal: any) => {
    console.log('########', newVal, oldVal)
})
/*
情况5：监视reactive定义对象的某些属性，依旧是数组，每个数组需要编写为函数
*/
watch([() => d.name, () => d.age], (newVal: any, oldVal: any) => {
    console.log('!!!!!!!!!', newVal, oldVal)
})
watchEffect(() => {
    const x: number = cnt.value
    const y: string = c.value.name
    console.log('触发回调', x, y)
})
/*解构赋值一个reactive对象后，对应的解构变量不是响应式的，使用toRef保证依旧有响应式属性
为了保证只用响应式对象的一个属性，但是不失去响应式特性，可以使用toRef
格式toRef(对象，属性名)，
*/
const list=useTalkStore().talkList
//挂载时渲染组件
onMounted(() => {
    changecName()
    changDName()
    const age = toRef(d, 'age')
    console.log(age.value)
    const e=toRefs(d)
    console.log(e)
})
</script>
<style scoped></style>